#!/usr/bin/env python
# coding=utf-8
"""
@file: date_util.py
@contact: bianzhiwei@iyoujia.com
@time   : 2019/4/1 11:04 
@Desc   :
"""
import time
import logging
import calendar
import datetime
from datetime import timezone
from dateutil.relativedelta import relativedelta


def curdate(days=1, dft='%Y-%m-%d'):
    """
    :param days:相对今天减去的天数  默认相对今天减去一天  即昨天
    :param dft:
    :return:
    """
    recdate = datetime.date.today() - datetime.timedelta(days=days)
    return recdate


def month_days(dt, dft='%Y-%m-%d'):

    # 求后一个月的第一天
    today = datetime.datetime.strptime(str(dt), dft)
    return calendar.monthrange(today.year, today.month)[1]  # 获取一个月有多少天


def cur_month_first(days=1, dt=None, dft='%Y-%m-%d'):
    """
    :param days: 获取本月几号 days为几 默认为本月1号
    :param dt: 相对日期
    :param dft: 日期格式 默认为'%Y-%m-%d'
    :return: 相对于dt那月的第一天
    """
    # try:
    today = datetime.datetime.strptime(str(dt), dft) if dt else datetime.date.today()
    return datetime.date(today.year, today.month, days)
    # except Exception as e:
    #     logging.exception(dt)
    #     logging.exception(e)


def datetime_to_str(dt, dft='%Y-%m-%d'):
    return datetime.datetime.strptime(dt, dft)


# def datetime_to_date(dt, dft="%Y-%m-%d %H:%M:%S"):
#     dt = datetime.datetime.strptime(str(dt), dft)
#     print(dt, type(dt))
#     return dt


def cur_month_last(dt=None, dft='%Y-%m-%d'):
    """
    # :param days: 获取本月几号 days为几 默认为本月1号
    :param dt: 相对日期
    :param dft: 日期格式 默认为'%Y-%m-%d'
    :return: 相对于dt那月的最后一天
    """
    today = datetime.datetime.strptime(str(dt), dft) if dt else datetime.date.today()
    days_num = calendar.monthrange(today.year, today.month)[1]
    return datetime.date(today.year, today.month, days_num)


def last_month_last(dt, dft='%Y-%m-%d'):
    """
    获取上个月的月末
    :param dt:
    :param dft:
    :return:
    """
    cur_month_first_time = cur_month_first(dt=dt, dft=dft)
    return cur_month_first_time - datetime.timedelta(days=1)


def next_month_first(dt=None, dft='%Y-%m-%d'):
    """
    默认为下月一号   day 代表相对下月一号的时间偏移
    :param dt:
    :param dft:
    :return:
    """
    # 求后一个月的第一天
    today = datetime.datetime.strptime(str(dt), dft) if dt else datetime.date.today()
    days_num = calendar.monthrange(today.year, today.month)[1]  # 获取一个月有多少天
    first_day_of_next_month = cur_month_first(dt=dt, dft=dft) + datetime.timedelta(days=days_num)
    return first_day_of_next_month


def date_to_str(date, dft='%Y-%m-%d'):
    """
    将datetime.date 类型转为 str
    :param date:
    :param dft:
    :return:
    """
    return date.strftime(dft)


def str_to_datetime(date, dft='%Y-%m-%d'):
    # if isinstance(date, datetime.datetime) or isinstance(date, datetime.date):
    #     raise '同种类型转换失败'
    # else:
    """
    将str 类型 转为 datetime.datetime 类型
    :param date:
    :param dft:
    :return: 返回的格式是"%Y-%m-%d %H:%M:%S"
    """
    return datetime.datetime.strptime(str(date), dft)  # .strftime("%Y-%m-%d")


def str_to_date(date, dft='%Y-%m-%d'):
    # if isinstance(date, datetime.datetime) or isinstance(date, datetime.date):
    #     raise '同种类型转换失败'
    # else:
    """

    :param date:
    :param dft:
    :return: 返回的格式是"%Y-%m-%d" 类型是 datetime.date
    """
    dt = datetime.datetime.strptime(str(date), dft)
    return datetime.date(dt.year, dt.month, dt.day)


def date_add(dt=None, days=1, months=0, years=0, dft='%Y-%m-%d', **kw):
    """
    将日期加几天
    :param dt:
    :param years:
    :param months:
    :param days:
    :param dft:
    :return:
    """
    # 先将日期转为 datetime.date 类型
    dt = str_to_date(date=dt, dft=dft)
    return dt + relativedelta(days=days, months=months, years=years, **kw)


def date_sub(dt=None, days=1, months=0, years=0, dft='%Y-%m-%d', **kw):
    """
    将日期减几天  默认
    :param dt:
    :param years:
    :param months:
    :param days:
    :param dft:
    :param kw:dt1=None, dt2=None,
                 years=0, months=0, days=0, leapdays=0, weeks=0,
                 hours=0, minutes=0, seconds=0, microseconds=0,
                 year=None, month=None, day=None, weekday=None,
                 yearday=None, nlyearday=None,
                 hour=None, minute=None, second=None, microsecond=None
    :return:
    """
    # 先将日期转为 datetime.date 类型
    dt = str_to_date(date=dt, dft=dft)
    return dt - relativedelta(days=days, months=months, years=years, **kw)


def date_sub_date(dt_st, dt_et, include_st=False, dft='%Y-%m-%d'):
    """
    计算两个日期相减
    :param dt_st:
    :param dt_et:
    :param dft:
    :param include_st: 是否包含开始时间
    :return:
    """

    dt_st = time.strptime(str(dt_st), dft)
    dt_et = time.strptime(str(dt_et), dft)
    # 根据上面需要计算日期还是日期时间，来确定需要几个数组段。下标0表示年，小标1表示月，依次类推...
    # date1=datetime.datetime(date1[0],date1[1],date1[2],date1[3],date1[4],date1[5])
    # date2=datetime.datetime(date2[0],date2[1],date2[2],date2[3],date2[4],date2[5])
    dt_st = datetime.datetime(dt_st[0], dt_st[1], dt_st[2])
    dt_et = datetime.datetime(dt_et[0], dt_et[1], dt_et[2])
    # 返回两个变量相差的值，就是相差天数
    if include_st:
        return (dt_et - dt_st).days + 1
    return (dt_et - dt_st).days


def time_stamp():
    """
    获取毫秒级时间戳 1558676613687
    :return:
    """
    return str(int(round(time.time() * 1000)))


def datetime_now():
    """
    获取当前时间的datetime时间
    :return:
    """
    return datetime.datetime.now()


def today_str(dt=None):
    """
    获取今天的字符串类型日期
    :return:
    """
    dt = dt if dt else datetime.date.today()
    return dt.__str__()


def utc_to_local(utc_dt):
    return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)


if __name__ == '__main__':
    # a = next_month_first('2018-03-02')
    # print(type(a), a)
    # b = str_to_date(str(a))
    # print(type(b), b)
    # a = date_add(curdate())
    # print(a)
    a = date_sub_date('2019-10-03', '2019-10-05', include_st=True
                      , dft='%Y-%m-%d')
    print(a)
    print(date_sub_date('2019-10-16', '2019-10-17', dft='%Y-%m-%d'))
